#ifndef __COMUN_ARCHIVO_H
#define __COMUN_ARCHIVO_H

/*****************************************************************************
*                     Organizaci�n de Datos - 75.06                          *
*                         C�tedra Lic. Servetto                              *
*            Facultad de Ingenier�a - Universidad de Buenos Aires            *
******************************************************************************/ 

#include <string>
#include <list>

using namespace std;

namespace Comun
{

	const int NoHayMasGrupos = -1;
	const int TamanioPredeterminado = 4096;

	struct ClaveValor{
	
		public:

		string Clave;
		string Valor;

	};

	enum TipoRegistro
	{

		Cadena,
		Caracter,
		Entero,
		EnteroLargo,
		Fecha,
		Booleano,
		Real

	};

	class ParserDeTipoRegistro
	{

		public:

		static TipoRegistro Parsear(string tipo);
		static TipoRegistro Parsear(char tipo);
		static char ConvertirACaracter(TipoRegistro tipo);
		static string Parsear(TipoRegistro tipo);

	};

	class Atributo
	{
	
		public:

		Atributo();
		Atributo(string nombre, string valor);
		~Atributo();
		string Nombre;
		string Valor;
		TipoRegistro Tipo;

	};

	typedef list<Atributo>::iterator IteradorDeAtributos;

	class Registro
	{

		public:

		Registro();
		~Registro();
		list<Comun::Atributo>& Atributos;
		bool operator == (const Registro&) const;
		// Indica si el registro fue marcado durante alguna busqueda
		// TODO: Revisar
		bool Marcado;
		int Tamanio;

		private:

		list<Comun::Atributo> inicializadorAtributos;
	};
	
	typedef list<Registro>::iterator IteradorDeRegistros;

	class Grupo
	{

		public:

		int GrupoId;
		list<Atributo>& Atributos;
		list<Registro>& Registros;

		Grupo();
		~Grupo();

		private:

		list<Atributo> inicializadorAtributos;
		list<Registro> inicializadorRegistros;

	};

	class MetadatosAtributo
	{

		public:

		string Nombre;
		TipoRegistro Tipo;

		MetadatosAtributo(string nombre, TipoRegistro tipo);
		~MetadatosAtributo();

	};

	typedef list<MetadatosAtributo>::iterator IteradorDeMetadatosDeAtributos;

	class MetadatosRegistro
	{

		public:

		list<MetadatosAtributo>& MetadatosAtributos;

		MetadatosRegistro();
		~MetadatosRegistro();

		private:

		list<MetadatosAtributo> inicializadorMetadatosAtributos;

	};

	class MetadatosGrupo
	{

		public:

		list<Comun::MetadatosAtributo>& MetadatosAtributos;
		Comun::MetadatosRegistro* MetadatosRegistro;

		MetadatosGrupo();
		~MetadatosGrupo();

		private:

		list<Comun::MetadatosAtributo> inicializadorMetadatosAtributos;

	};

	class MetadatosArchivo
	{

		public:

		string Nombre;
		Comun::MetadatosGrupo* MetadatosGrupo;
		int TamanioBloque;

		MetadatosArchivo(string nombre);
		~MetadatosArchivo();

	};

	// Enumera los distintos codigos de resultado de una operacion sobre el indice.
	enum CodigoResultado
	{

		// La operacion fue realizada con exito.
		Exito,
		// La operacion genero un sobreflujo sobre el grupo de registros.
		Sobreflujo,
		// La operacion genero un subflujo sobre el grupo de registros.
		Subflujo,
		// La operacion fallo porque no pudo encontrar la clave utilzada por la operacion.
		ClaveNoEncontrada,
		// Error de aplicacion.
		Error

	};


	class IArchivo
	{

		public:

		string Nombre;
		Comun::MetadatosArchivo* Metadatos;

		virtual int CrearGrupo(Comun::Grupo &grupo) = 0;
		virtual CodigoResultado GuardarGrupo(Comun::Grupo &grupo, bool omitirSubflujo = false) = 0;
		virtual Comun::Grupo& LeerGrupo(int grupoId) = 0;
		virtual void BorrarGrupo(int grupoId) = 0;
		virtual int PrimerGrupo() = 0;
		virtual int SiguienteGrupo(int grupoIdActual) = 0;

	};

}

#endif
